package com.cencat.common.utils;


import java.util.*;
import java.util.regex.Pattern;

import java.util.UUID;

/**
 * Cencat字符串工具类
 * 提供常用的字符串操作方法，扩展Apache Commons Lang3的StringUtils功能
 * 合并了StringUtils的所有功能
 * 
 * @author cencat
 * @since 2024-01-01
 */
public class CencatStringUtils {

    /**
     * 空字符串
     */
    public static final String EMPTY = "";

    /**
     * 空格字符串
     */
    public static final String SPACE = " ";

    /**
     * 换行符
     */
    public static final String LF = "\n";

    /**
     * 回车符
     */
    public static final String CR = "\r";

    /**
     * 制表符
     */
    public static final String TAB = "\t";

    /**
     * 常用分隔符
     */
    public static final String COMMA = ",";
    public static final String SEMICOLON = ";";
    public static final String COLON = ":";
    public static final String DOT = ".";
    public static final String SLASH = "/";
    public static final String BACKSLASH = "\\";
    public static final String PIPE = "|";
    public static final String UNDERSCORE = "_";
    public static final String HYPHEN = "-";

    /**
     * 手机号正则表达式
     */
    private static final Pattern MOBILE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");
    private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");

    /**
     * 邮箱正则表达式
     */
    private static final Pattern EMAIL_PATTERN = Pattern.compile(
            "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");

    /**
     * 身份证号正则表达式
     */
    private static final Pattern ID_CARD_PATTERN = Pattern.compile(
            "^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$");

    /**
     * 中文字符正则表达式
     */
    private static final Pattern CHINESE_PATTERN = Pattern.compile("[\\u4e00-\\u9fa5]");

    /**
     * 纯数字正则表达式
     */
    private static final Pattern NUMBER_PATTERN = Pattern.compile("^\\d+$");

    /**
     * 小数正则表达式
     */
    private static final Pattern DECIMAL_PATTERN = Pattern.compile("^\\d+\\.\\d+$");

    /**
     * 私有构造函数，防止实例化
     */
    private CencatStringUtils() {
        throw new UnsupportedOperationException("Utility class cannot be instantiated");
    }

    /**
     * 判断字符串是否为空或空白
     * 
     * @param str 字符串
     * @return true-空或空白，false-非空且非空白
     */
    public static boolean isBlank(String str) {
        return org.apache.commons.lang3.StringUtils.isBlank(str);
    }

    /**
     * 判断字符串是否非空且非空白
     * 
     * @param str 字符串
     * @return true-非空且非空白，false-空或空白
     */
    public static boolean isNotBlank(String str) {
        return org.apache.commons.lang3.StringUtils.isNotBlank(str);
    }

    /**
     * 判断字符串是否为空
     * 
     * @param str 字符串
     * @return true-空，false-非空
     */
    public static boolean isEmpty(String str) {
        return org.apache.commons.lang3.StringUtils.isEmpty(str);
    }

    /**
     * 判断字符串是否非空
     * 
     * @param str 字符串
     * @return true-非空，false-空
     */
    public static boolean isNotEmpty(String str) {
        return org.apache.commons.lang3.StringUtils.isNotEmpty(str);
    }

    /**
     * 去除字符串首尾空白字符
     * 
     * @param str 字符串
     * @return 去除首尾空白后的字符串
     */
    public static String trim(String str) {
        return org.apache.commons.lang3.StringUtils.trim(str);
    }

    /**
     * 安全的去除字符串首尾空白字符（null安全）
     * 
     * @param str 字符串
     * @return 去除首尾空白后的字符串，如果输入为null则返回null
     */
    public static String trimToNull(String str) {
        return org.apache.commons.lang3.StringUtils.trimToNull(str);
    }

    /**
     * 安全的去除字符串首尾空白字符（null转空字符串）
     * 
     * @param str 字符串
     * @return 去除首尾空白后的字符串，如果输入为null则返回空字符串
     */
    public static String trimToEmpty(String str) {
        return org.apache.commons.lang3.StringUtils.trimToEmpty(str);
    }

    /**
     * 字符串连接
     * 
     * @param elements 要连接的元素
     * @return 连接后的字符串
     */
    public static String join(Object... elements) {
        return org.apache.commons.lang3.StringUtils.join(elements);
    }

    /**
     * 使用分隔符连接字符串
     * 
     * @param elements 要连接的元素
     * @param separator 分隔符
     * @return 连接后的字符串
     */
    public static String join(Object[] elements, String separator) {
        return org.apache.commons.lang3.StringUtils.join(elements, separator);
    }

    /**
     * 使用分隔符连接集合元素
     * 
     * @param collection 集合
     * @param separator 分隔符
     * @return 连接后的字符串
     */
    public static String join(Collection<?> collection, String separator) {
        return org.apache.commons.lang3.StringUtils.join(collection, separator);
    }

    /**
     * 字符串分割
     * 
     * @param str 要分割的字符串
     * @param separator 分隔符
     * @return 分割后的字符串数组
     */
    public static String[] split(String str, String separator) {
        return org.apache.commons.lang3.StringUtils.split(str, separator);
    }

    /**
     * 首字母大写
     * 
     * @param str 字符串
     * @return 首字母大写的字符串
     */
    public static String capitalize(String str) {
        return org.apache.commons.lang3.StringUtils.capitalize(str);
    }

    /**
     * 首字母小写
     * 
     * @param str 字符串
     * @return 首字母小写的字符串
     */
    public static String uncapitalize(String str) {
        return org.apache.commons.lang3.StringUtils.uncapitalize(str);
    }

    /**
     * 驼峰命名转下划线命名
     * 
     * @param camelCase 驼峰命名字符串
     * @return 下划线命名字符串
     */
    public static String camelToSnake(String camelCase) {
        if (isBlank(camelCase)) {
            return camelCase;
        }
        return camelCase.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
    }

    /**
     * 下划线命名转驼峰命名
     * 
     * @param snakeCase 下划线命名字符串
     * @return 驼峰命名字符串
     */
    public static String snakeToCamel(String snakeCase) {
        if (isBlank(snakeCase)) {
            return snakeCase;
        }
        
        StringBuilder result = new StringBuilder();
        String[] parts = snakeCase.split("_");
        
        for (int i = 0; i < parts.length; i++) {
            String part = parts[i];
            if (i == 0) {
                result.append(part.toLowerCase());
            } else {
                result.append(capitalize(part.toLowerCase()));
            }
        }
        
        return result.toString();
    }

    /**
     * 验证手机号格式
     * 
     * @param mobile 手机号
     * @return true-格式正确，false-格式错误
     */
    public static boolean isMobile(String mobile) {
        if (isBlank(mobile)) {
            return false;
        }
        return MOBILE_PATTERN.matcher(mobile).matches();
    }

    /**
     * 验证邮箱格式
     * 
     * @param email 邮箱
     * @return true-格式正确，false-格式错误
     */
    public static boolean isEmail(String email) {
        if (isBlank(email)) {
            return false;
        }
        return EMAIL_PATTERN.matcher(email).matches();
    }

    /**
     * 验证身份证号格式
     * 
     * @param idCard 身份证号
     * @return true-格式正确，false-格式错误
     */
    public static boolean isIdCard(String idCard) {
        if (isBlank(idCard)) {
            return false;
        }
        return ID_CARD_PATTERN.matcher(idCard).matches();
    }

    /**
     * 手机号脱敏
     * 
     * @param mobile 手机号
     * @return 脱敏后的手机号
     */
    public static String maskMobile(String mobile) {
        if (isBlank(mobile) || mobile.length() != 11) {
            return mobile;
        }
        return mobile.substring(0, 3) + "****" + mobile.substring(7);
    }

    /**
     * 邮箱脱敏
     * 
     * @param email 邮箱
     * @return 脱敏后的邮箱
     */
    public static String maskEmail(String email) {
        if (isBlank(email) || !email.contains("@")) {
            return email;
        }
        
        String[] parts = email.split("@");
        String username = parts[0];
        String domain = parts[1];
        
        if (username.length() <= 2) {
            return "*@" + domain;
        }
        
        return username.charAt(0) + "***" + username.charAt(username.length() - 1) + "@" + domain;
    }

    /**
     * 身份证号脱敏
     * 
     * @param idCard 身份证号
     * @return 脱敏后的身份证号
     */
    public static String maskIdCard(String idCard) {
        if (isBlank(idCard) || idCard.length() != 18) {
            return idCard;
        }
        return idCard.substring(0, 6) + "********" + idCard.substring(14);
    }

    /**
     * 生成随机字符串
     * 
     * @param length 长度
     * @return 随机字符串
     */
    public static String randomString(int length) {
        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        StringBuilder sb = new StringBuilder();
        
        for (int i = 0; i < length; i++) {
            int index = (int) (Math.random() * chars.length());
            sb.append(chars.charAt(index));
        }
        
        return sb.toString();
    }

    /**
     * 生成随机数字字符串
     * 
     * @param length 长度
     * @return 随机数字字符串
     */
    public static String randomNumeric(int length) {
        StringBuilder sb = new StringBuilder();
        
        for (int i = 0; i < length; i++) {
            sb.append((int) (Math.random() * 10));
        }
        
        return sb.toString();
    }

    // ========== 扩展功能方法（来自StringUtils） ==========

    /**
     * 判断所有字符串是否都为空
     * @param strs 字符串数组
     * @return 是否都为空
     */
    public static boolean isAllEmpty(String... strs) {
        if (strs == null || strs.length == 0) {
            return true;
        }
        for (String str : strs) {
            if (isNotEmpty(str)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断任意字符串是否为空
     * @param strs 字符串数组
     * @return 是否有空字符串
     */
    public static boolean isAnyEmpty(String... strs) {
        if (strs == null || strs.length == 0) {
            return true;
        }
        for (String str : strs) {
            if (isEmpty(str)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取默认值
     * @param str 原字符串
     * @param defaultValue 默认值
     * @return 处理后的字符串
     */
    public static String defaultIfEmpty(String str, String defaultValue) {
        return isEmpty(str) ? defaultValue : str;
    }

    /**
     * 获取默认值（空白处理）
     * @param str 原字符串
     * @param defaultValue 默认值
     * @return 处理后的字符串
     */
    public static String defaultIfBlank(String str, String defaultValue) {
        return isBlank(str) ? defaultValue : str;
    }

    /**
     * 截取字符串
     * @param str 原字符串
     * @param maxLength 最大长度
     * @return 截取后的字符串
     */
    public static String truncate(String str, int maxLength) {
        if (isEmpty(str) || maxLength <= 0) {
            return str;
        }
        return str.length() <= maxLength ? str : str.substring(0, maxLength);
    }

    /**
     * 截取字符串并添加省略号
     * @param str 原字符串
     * @param maxLength 最大长度
     * @param suffix 后缀（如"..."）
     * @return 截取后的字符串
     */
    public static String truncateWithSuffix(String str, int maxLength, String suffix) {
        if (isEmpty(str) || maxLength <= 0) {
            return str;
        }
        if (str.length() <= maxLength) {
            return str;
        }
        String suffixStr = defaultIfEmpty(suffix, "...");
        int truncateLength = maxLength - suffixStr.length();
        if (truncateLength <= 0) {
            return suffixStr;
        }
        return str.substring(0, truncateLength) + suffixStr;
    }

    /**
     * 驼峰转下划线
     * @param str 驼峰字符串
     * @return 下划线字符串
     */
    public static String camelToUnderscore(String str) {
        if (isEmpty(str)) {
            return str;
        }
        return str.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
    }

    /**
     * 下划线转驼峰
     * @param str 下划线字符串
     * @return 驼峰字符串
     */
    public static String underscoreToCamel(String str) {
        if (isEmpty(str)) {
            return str;
        }
        String[] parts = str.toLowerCase().split(UNDERSCORE);
        StringBuilder result = new StringBuilder(parts[0]);
        for (int i = 1; i < parts.length; i++) {
            result.append(capitalize(parts[i]));
        }
        return result.toString();
    }

    /**
     * 连字符转驼峰
     * @param str 连字符字符串
     * @return 驼峰字符串
     */
    public static String hyphenToCamel(String str) {
        if (isEmpty(str)) {
            return str;
        }
        String[] parts = str.toLowerCase().split(HYPHEN);
        StringBuilder result = new StringBuilder(parts[0]);
        for (int i = 1; i < parts.length; i++) {
            result.append(capitalize(parts[i]));
        }
        return result.toString();
    }

    /**
     * 安全的字符串分割
     * @param str 字符串
     * @param delimiter 分隔符
     * @return 分割后的数组
     */
    public static String[] splitSafe(String str, String delimiter) {
        if (isEmpty(str)) {
            return new String[0];
        }
        return str.split(Pattern.quote(delimiter));
    }

    /**
     * 安全的字符串分割（返回List）
     * @param str 字符串
     * @param delimiter 分隔符
     * @return 分割后的List
     */
    public static List<String> splitToList(String str, String delimiter) {
        if (isEmpty(str)) {
            return new ArrayList<>();
        }
        return Arrays.asList(str.split(Pattern.quote(delimiter)));
    }

    /**
     * 判断字符串是否包含指定子串
     * @param str 字符串
     * @param searchStr 搜索字符串
     * @return 是否包含
     */
    public static boolean contains(String str, String searchStr) {
        if (str == null || searchStr == null) {
            return false;
        }
        return str.contains(searchStr);
    }

    /**
     * 判断字符串是否包含指定子串（忽略大小写）
     * @param str 字符串
     * @param searchStr 搜索字符串
     * @return 是否包含
     */
    public static boolean containsIgnoreCase(String str, String searchStr) {
        if (str == null || searchStr == null) {
            return false;
        }
        return str.toLowerCase().contains(searchStr.toLowerCase());
    }

    /**
     * 判断字符串是否以指定前缀开始
     * @param str 字符串
     * @param prefix 前缀
     * @return 是否以指定前缀开始
     */
    public static boolean startsWith(String str, String prefix) {
        if (str == null || prefix == null) {
            return false;
        }
        return str.startsWith(prefix);
    }

    /**
     * 判断字符串是否以指定后缀结束
     * @param str 字符串
     * @param suffix 后缀
     * @return 是否以指定后缀结束
     */
    public static boolean endsWith(String str, String suffix) {
        if (str == null || suffix == null) {
            return false;
        }
        return str.endsWith(suffix);
    }

    /**
     * 验证手机号（兼容方法）
     * @param phone 手机号
     * @return 是否有效
     */
    public static boolean isValidPhone(String phone) {
        return isMobile(phone);
    }

    /**
     * 验证邮箱（兼容方法）
     * @param email 邮箱
     * @return 是否有效
     */
    public static boolean isValidEmail(String email) {
        return isEmail(email);
    }

    /**
     * 验证身份证号（兼容方法）
     * @param idCard 身份证号
     * @return 是否有效
     */
    public static boolean isValidIdCard(String idCard) {
        return isIdCard(idCard);
    }

    /**
     * 判断是否包含中文
     * @param str 字符串
     * @return 是否包含中文
     */
    public static boolean containsChinese(String str) {
        if (isEmpty(str)) {
            return false;
        }
        return CHINESE_PATTERN.matcher(str).find();
    }

    /**
     * 判断是否为纯数字
     * @param str 字符串
     * @return 是否为纯数字
     */
    public static boolean isNumber(String str) {
        if (isEmpty(str)) {
            return false;
        }
        return NUMBER_PATTERN.matcher(str).matches();
    }

    /**
     * 判断是否为小数
     * @param str 字符串
     * @return 是否为小数
     */
    public static boolean isDecimal(String str) {
        if (isEmpty(str)) {
            return false;
        }
        return DECIMAL_PATTERN.matcher(str).matches() || NUMBER_PATTERN.matcher(str).matches();
    }

    /**
     * 手机号掩码（兼容方法）
     * @param phone 手机号
     * @return 掩码后的手机号
     */
    public static String maskPhone(String phone) {
        return maskMobile(phone);
    }

    /**
     * 银行卡号掩码
     * @param bankCard 银行卡号
     * @return 掩码后的银行卡号
     */
    public static String maskBankCard(String bankCard) {
        if (isEmpty(bankCard) || bankCard.length() < 8) {
            return bankCard;
        }
        return bankCard.substring(0, 4) + " **** **** " + bankCard.substring(bankCard.length() - 4);
    }

    /**
     * 生成随机数字字符串（兼容方法）
     * @param length 长度
     * @return 随机数字字符串
     */
    public static String randomNumber(int length) {
        return randomNumeric(length);
    }

    /**
     * 生成UUID（去掉连字符）
     * @return UUID字符串
     */
    public static String uuid() {
        return UUID.randomUUID().toString().replace(HYPHEN, EMPTY);
    }

    /**
     * 生成带连字符的UUID
     * @return UUID字符串
     */
    public static String uuidWithHyphen() {
        return UUID.randomUUID().toString();
    }

    /**
     * 生成随机字符串（别名方法）
     * 
     * @param length 长度
     * @return 随机字符串
     */
    public static String generateRandomString(int length) {
        return randomString(length);
    }
}